package org.robot.scm.platform.registry;

import static java.lang.Runtime.getRuntime;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jcraft.jsch.Session;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.util.List;
import java.util.Map;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.robot.scm.platform.AbstractMonitor;
import org.robot.scm.platform.AbstractRegistry;
import org.robot.scm.platform.server.ScmHttpServer;
import org.robot.scm.pojos.config.BaseConfig;
import org.robot.scm.pojos.enums.PlatformEnum;
import org.robot.scm.pojos.platform.server.SshMySql;

/**
 * @Author : Awn create on 2024/5/12 19:36
 */
@Slf4j
public class HikariRegistry extends AbstractRegistry {

    @Getter
    private final static Map<String, HikariDataSource> hikariMap = Maps.newHashMap();

    @Override
    public int getOrder() {
        return 2;
    }

    @Override
    public void registry() {
        if (!AbstractMonitor.mainConfig.getEnables().contains(PlatformEnum.SQL.getVal())) {
            return;
        }
        try {
            BaseConfig config = ScmHttpServer.getTargetConfig(PlatformEnum.SQL);
            List<SshMySql> sshMySqls = config.getCurrentPlatform().getSshMysqlDetails();

            for (SshMySql mySql : sshMySqls) {
                // todo...awn
                // 16、19、23 无需要hikari
                if (Lists.newArrayList("mec16", "mec19", "mec23").contains(mySql.getName())) {
                    continue;
                }
                hikariMap.put(mySql.getName(), initHikari(mySql));
                log.info("init hikari {} ... ok", mySql.getName());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        getRuntime().addShutdownHook(new Thread(() -> {
            hikariMap.values().forEach(HikariDataSource::close);
            log.info("close hikari datasource ... ok");
        }));
    }

    private static HikariDataSource initHikari(SshMySql mysql) {
        try {
            Session session = SessionRegistry.getSessionMap().get(mysql.getName());

            // 在堡垒机场景下，sshFwdHost是堡垒机后面的MySQL服务器地址
            // 端口转发：将本地端口转发到远程MySQL服务器
            session.setPortForwardingL(mysql.getSshFwdPort(), mysql.getSshFwdHost(), 3306);
            HikariConfig config = new HikariConfig();
            // 关键修改：连接到本地转发的端口，而不是远程主机
            // 在堡垒机场景下，MySQL连接应该指向localhost和转发的端口
            config.setJdbcUrl("jdbc:mysql://localhost:" + mysql.getSshFwdPort() + "/mysql?sessionVariables=sql_log_bin=1");
            config.setUsername(mysql.getMysqlUser());
            config.setPassword(mysql.getMysqlPass());
            config.addDataSourceProperty("cachePrepStmts", "true");
            config.addDataSourceProperty("prepStmtCacheSize", "250");
            config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
            config.setPoolName(mysql.getName());
            config.setMaximumPoolSize(mysql.getMaximumPoolSize()); // 2c2g的服务器 最大2个 8个数据源
            config.setMinimumIdle(mysql.getMinimumIdle());
            config.setConnectionTimeout(30000); // 30秒超时
            config.setMaxLifetime(1800000); // 30分钟最大生命周期
            config.setIdleTimeout(60000);
            config.setConnectionTestQuery("SELECT 1");
            return new HikariDataSource(config);
        } catch (Exception e) {
            log.error("init hikari {} ... error", mysql.getName(), e);
            throw new RuntimeException(e);
        }
    }

}
